package com.ig.presentacion.modelos.desembolso.calculos;

import java.util.Calendar;
import java.util.Date;

//import com.ig.utilitarios.Modalidad;

/**
 * Clase encargada de generar los planes de amortizaci?n
 * 	1	Cuota Variable, TasaVariable
 * 	2	Cuota Variable, Tasa Fija
 * 	3	Cuota Fija, Tasa Fija
 *
 * Cada uno de estos metodos supone
 * 	que el interes ya esta convertido a la frecuencia
 *
 * @author jsanchez
 *
 */
public class PlanesAmortizacion{
    private Fechas fechas= null;
    private CuotaVariableTasaVariable cuotaVariableTasaVariable= null;
    private CuotaFijaTasaFija cuotaFijaTasaFija= null;
    private CuotaVariableTasaFija cuotaVariableTasaFija= null;
    boolean debug=false;
    
    public PlanesAmortizacion(){
        fechas= new Fechas();
        cuotaVariableTasaVariable= new CuotaVariableTasaVariable(fechas);
        cuotaFijaTasaFija= new CuotaFijaTasaFija(fechas);
        cuotaVariableTasaFija= new CuotaVariableTasaFija(fechas);
    }
    
    public void setPeriodoGracia(int periodoGracia) {
        cuotaVariableTasaVariable.setPeriodoGracia(periodoGracia);
        cuotaFijaTasaFija.setPeriodoGracia(periodoGracia);
        cuotaVariableTasaFija.setPeriodoGracia(periodoGracia);
    }
    
    public PlanesAmortizacion(boolean debug){
        fechas= new Fechas();
        this.debug=debug;
        cuotaVariableTasaVariable= new CuotaVariableTasaVariable(fechas,debug);
        cuotaFijaTasaFija= new CuotaFijaTasaFija(fechas,debug);
        cuotaVariableTasaFija = new CuotaVariableTasaFija(fechas,debug);
    }
    
    /**
     * @param fechaPagoInicial
     *
     * Ejemplo: 20061231
     */
    public void setFechaPagoInicial(String fechaPagoInicial) {
        fechas.setAnno(fechaPagoInicial.substring(0,4));
        fechas.setMes(fechaPagoInicial.substring(4,6));
        fechas.setDia(fechaPagoInicial.substring(6,8));
    }
    /**
     * @param fechaPagoInicial
     *
     * Ejemplo: 20061231
     */
    public void setFechaPagoInicial(Date fechaPagoInicial) {
        String fecha=fechaPagoInicial.toString();
        Integer dia=Integer.valueOf(fecha.substring(8,10));
        Integer mes=Integer.valueOf(fecha.substring(5,7));
        Integer anio=Integer.valueOf(fecha.substring(0,4));
        if(dia<=9)
            fechas.setDia("0"+dia);
        else
            fechas.setDia(dia.toString());
        
        if(mes<=9)
            fechas.setMes("0"+mes);
        else
            fechas.setMes(mes.toString());
        fechas.setAnno(anio.toString());
    }
    
    public java.sql.Date addMes(int meses,Long fecha){
        Calendar cal=Calendar.getInstance();
        cal.setTimeInMillis(fecha);
        cal.add(cal.MONTH,meses);
        return new java.sql.Date(cal.getTimeInMillis());
    }
    
    public java.sql.Date calcularFechaAnterior(Integer plazoPeriodo,Integer fecuencia, Long fechaFinal){
        Calendar cal=Calendar.getInstance();
        cal.setTimeInMillis(fechaFinal);
        int periodo=0;
        while(periodo<plazoPeriodo){
            cal.add(cal.MONTH,(-1*(fecuencia)));
            periodo++;
        }
        System.out.println("    Nueva fecha calculada "+new java.sql.Date(cal.getTimeInMillis()));
        return new java.sql.Date(cal.getTimeInMillis());
    }
    public java.sql.Date calcularFechaAnterior(Long fechaCorte,Integer fecuencia, Long fechaFinal){
        Calendar cal=Calendar.getInstance();
        cal.setTimeInMillis(fechaFinal);
        while(fechaCorte<cal.getTimeInMillis()){
            cal.add(cal.MONTH,(-1*(fecuencia)));
        }
        System.out.println("    Nueva fecha calculada "+new java.sql.Date(cal.getTimeInMillis()));
        return new java.sql.Date(cal.getTimeInMillis());
    }
    
    /**
     * @param frecuencia
     * :puede ser
     * 	Fechas.DIARION=1
     * 	Fechas.SEMANAL=2
     * 	Fechas.MENSUAL=3
     * 	Fechas.TRIMESTRAL=4
     * 	Fechas.SEMESTRAL=5
     * 	Fechas.ANUAL=6
     */
    public void setTipoFrecuencia(int tipoFrecuencia) {
        this.fechas.setTipoFrecuencia(tipoFrecuencia);
    }
    
    /**
     * tipo de calendario para el calculos de los intereses
     *
     * @param calendario
     * 	puedes ser:
     *
     * 	Calendarios.CALENDARIO_REAL=1 todos los a?os son de 365 o 366 dias y los meses de 28, 29, 30, 31 dias
     * 	Calendarios.CALENDARIO_COMERCIAL=2 todos los a?os tines 360 dias u los meses de 30 dias
     * 	Calendarios.CALENDARIO_365=3 todos los meses tienen 365 dias y los meses de 28, 30, 31 dias
     */
    public void setCalendario(int calendario) {
        this.fechas.setCalendario(calendario);
    }
    
    /**
     * calcula el plan de amortizacion para cuotas varibles y tasa variables
     *
     * @param monto 				: valor	desembolsado
     * @param interesVariable	: vector de intereses ya convertidos a frecuencia de pago
     * @param plazo				: frecuencia de pago
     * @return					: matriz con filas=plazo.leng & columnas 5[fecha, cuota, interes, capital, saldocapital]
     */
    public Object[][] calcularPlanCuotaVariableTasaVariable(Double monto, Double[] interesVariable, Integer plazo){
        return cuotaVariableTasaVariable.calcularPlanCuotaVariableTasaVariable(monto, interesVariable,plazo);
    }
    
    
    /**
     * calcula el plan de amortizacion para cuotas fijas y tasa fija
     *
     * @param monto 				: valor	desembolsado
     * @param interesVariable	: vector de intereses ya convertidos a frecuencia de pago
     * @param plazo				: frecuencia de pago
     * @modalidad				: vencida o anticipada
     * @return					: matriz con filas=plazo.leng & columnas 5[fecha, cuota, interes, capital, saldocapital]
     */
    public Object[][] calcularPlanCuotaFijaTasaFija(Double monto, Double interes, Integer plazo, Integer modalidad,Integer frecuenciaPagoCapital,Integer frecuenciaPagoInteres,Integer frecuenciaPlazo)throws Exception{
        cuotaFijaTasaFija.setCUOTA(null);
        return cuotaFijaTasaFija.calcularPlanCuotaFijaTasaFija(monto, interes, plazo, modalidad,frecuenciaPagoCapital,frecuenciaPagoInteres,frecuenciaPlazo);
        //return cuotaFijaTasaFija.calcularPlanCuotaFijaTasaFija(monto, interes, plazo, modalidad);
    }

    /**
     * calcula el plan de amortizacion para cuotas fijas y tasa fija
     *
     * @param monto 				: valor	desembolsado
     * @param interesVariable	: vector de intereses ya convertidos a frecuencia de pago
     * @param plazo				: frecuencia de pago
     * @modalidad				: vencida o anticipada
     * @return					: matriz con filas=plazo.leng & columnas 5[fecha, cuota, interes, capital, saldocapital]
     */
    public Object[][] calcularPlanCuotaFijaTasaFija(Double monto, Double interes, Integer plazo, Integer modalidad,Integer frecuenciaPagoCapital,Integer frecuenciaPagoInteres,Integer frecuenciaPlazo,Double valorCuota)throws Exception{
        cuotaFijaTasaFija.setCUOTA(valorCuota);
        return cuotaFijaTasaFija.calcularPlanCuotaFijaTasaFija(monto, interes, plazo, modalidad,frecuenciaPagoCapital,frecuenciaPagoInteres,frecuenciaPlazo);
        //return cuotaFijaTasaFija.calcularPlanCuotaFijaTasaFija(monto, interes, plazo, modalidad);
    }
    
    /**
     * calcula el plan de amortizacion para cuotas varibles y tasa fija
     * @param monto 				: valor	desembolsado
     * @param interes			: interes ya convertido a frecuencia de pago
     * @param plazo				: es la frecuencia de pago
     * @param capital			: vector de abonos a capital en frecuencias preferidas
     * 								ej:
     *      								Double[] vector= new Vector[4];
     * 									vector[1-1]=2000000;
     * 									vector[4-1]=2000000;
     * 										No implica que las demas pocisiones sean nulas.
     * @return					: matriz con el plan acalculado
     */
    public Object[][] calcularPlanCuotaVariableTasaFija(Double monto, double interes, Integer plazo,Double[] abonoCapital){
        return cuotaVariableTasaFija.calcularPlanCuotaVariableTasaFija(monto, interes, plazo,abonoCapital);
    }
    
    public Integer getPeriodo360Periodos(Long fechaIncial, Long fechaFinal,Integer frecuencia) {
        Integer plazo=this.getPeriodo360Dias(fechaIncial,fechaFinal);
        plazo=plazo%(frecuencia*30)>0?(plazo/(frecuencia*30))+1:plazo/(frecuencia*30);
        return plazo;
    }
    
    
    public Integer getPeriodo360Dias(Long fechaIncial, Long fechaFinal) {
        
        Calendar fecha1=Calendar.getInstance();
        fecha1.setTimeInMillis(fechaFinal);
        fecha1.set(fecha1.HOUR_OF_DAY,fecha1.get(fecha1.HOUR_OF_DAY)*-1);
        fecha1.set(fecha1.SECOND,fecha1.get(fecha1.SECOND)*-1);
        fecha1.set(fecha1.MINUTE,fecha1.get(fecha1.MINUTE)*-1);
        fecha1.set(fecha1.MILLISECOND,fecha1.get(fecha1.MILLISECOND)*-1);
        
        Calendar fecha2=Calendar.getInstance();
        fecha2.setTimeInMillis(fechaIncial);
        fecha2.set(fecha2.HOUR_OF_DAY,fecha2.get(fecha2.HOUR_OF_DAY)*-1);
        fecha2.set(fecha2.SECOND,fecha2.get(fecha2.SECOND)*-1);
        fecha2.set(fecha2.MINUTE,fecha2.get(fecha2.MINUTE)*-1);
        fecha2.set(fecha2.MILLISECOND,fecha2.get(fecha2.MILLISECOND)*-1);
        
        if(fecha2.getTimeInMillis()==fecha1.getTimeInMillis())
            return 0;
        
        Calendar clon=(Calendar) fecha1.clone();
        clon.add(clon.DATE,-1);
        
        if(clon.getTimeInMillis()==fecha2.getTimeInMillis())
            return 1;
        /////////
        Integer YEAR1=fecha1.get(Calendar.YEAR);
        Integer YEAR2=fecha2.get(Calendar.YEAR);
        Integer MONTH1=fecha1.get(Calendar.MONTH);
        Integer MONTH2=fecha2.get(Calendar.MONTH);
        Integer DAY_OF_MONTH1=fecha1.get(Calendar.DAY_OF_MONTH);
        Integer DAY_OF_MONTH2=fecha2.get(Calendar.DAY_OF_MONTH);
        
        //alteramos el dia para ver el comportamiento del calendario
        fecha1.set(Calendar.DAY_OF_MONTH,fecha1.get(Calendar.DAY_OF_MONTH)+1);
        Integer nuevoMes=fecha1.get(Calendar.MONTH);
        Integer nuevoAnio=fecha1.get(Calendar.YEAR);
        Boolean cambioMes=!nuevoMes.equals(MONTH1)?true:false;
        Boolean cambioAnio=!nuevoAnio.equals(YEAR1)?true:false;
        
        Boolean ultimoDiaDelMesFecha1=(cambioMes || cambioAnio)?true:false;
        YEAR2=(YEAR1-YEAR2)*360;
        MONTH2=(MONTH1-MONTH2)*30;
        DAY_OF_MONTH2=(ultimoDiaDelMesFecha1?30:DAY_OF_MONTH1)-DAY_OF_MONTH2;
        
        Integer plazo=(YEAR2+DAY_OF_MONTH2+MONTH2);
        return plazo;
    }
}